/*
 * db_sqlite.cpp
 *
 *  Created on: 2017年3月11日
 *      Author: work
 */

#include <os/db/db_sqlite.hpp>
#include <string>

namespace iotplat {

    CDbSqlite::CDbSqlite(const char *dbName, const char *host, short port) : CDb(dbName, host, port),
                                                                             m_db(0) {
    }

    CDbSqlite::~CDbSqlite() {
        if (m_db != 0)
            sqlite3_close(m_db);
    }

    CDb::EDbType CDbSqlite::dbType() {
        return DtSqlite;
    }

    bool CDbSqlite::isConnected() {
        return m_db != 0;
    }

    bool CDbSqlite::connect(const char *, const char *) {
        std::string dbFile = "/media/sf_git/iot_plat/SHIP-Disengage/bin/" + m_dbName + ".db3";
        int rc = sqlite3_open(dbFile.c_str(), &m_db);
        if (rc == SQLITE_OK) {
            //log().debug(THISMODULE "打开数据库%s",dbFile.c_str());
            sqlite3_busy_timeout(m_db, 1000);
            return true;
        } else {
            //log().warnning( THISMODULE "打开数据%s失败：%s",dbFile.c_str(),sqlite3_errmsg(m_db));
            return false;
        }
    }

    void CDbSqlite::disconnect() {
        if (m_db != 0) {
            sqlite3_close(m_db);
            m_db = 0;
        }
    }

    bool CDbSqlite::exec(const char *sql) {
        if (m_db != 0) {
            int rt;
            int cnt = 0;
            while (true) {
                rt = sqlite3_exec(m_db, sql, 0, 0, 0);
                if (rt == SQLITE_LOCKED || rt == SQLITE_BUSY) {
                    if (cnt > 100)
                        break;
                    ++cnt;
                    usleep(100000);
                } else
                    break;
            }

            if (rt == SQLITE_OK)
                return true;
            else {
                //log().warnning(THISMODULE "执行失败：'%s' : %s",sql,sqlite3_errmsg(m_db));
                return false;
            }
        }

        return false;
    }

    int64_t CDbSqlite::execWithLastId(const char *sql) {
        if (!exec(sql))
            return -1;

        return sqlite3_last_insert_rowid(m_db);
    }

    CResultSet *CDbSqlite::query(const char *sql) {
        if (m_db != 0) {
            int rt;
            int cnt = 0;

            CResultSetSqlite *rs = new CResultSetSqlite();

            while (true) {
                rt = sqlite3_prepare(m_db, sql, -1, &rs->m_stmt, 0);
                if (rt == SQLITE_LOCKED || rt == SQLITE_BUSY) {
                    if (cnt > 100)
                        break;
                    ++cnt;
                    usleep(100000);
                } else
                    break;
            }

            if (SQLITE_OK != rt) {
                //log().warnning(THISMODULE "执行语句失败 '%s' :%s",sql,sqlite3_errmsg(m_db));
                delete rs;
                return NULL;
            } else {
                rs->m_size = 0;
                while (sqlite3_step(rs->m_stmt) == SQLITE_ROW) {
                    ++rs->m_size;
                }

                sqlite3_reset(rs->m_stmt);
                return rs;
            }
        }

        //log().debug(THISMODULE "sqlite库未打开");
        return NULL;
    }

/**
 * 获取匹配字符串表名
 * @param pattern
 * @param rs
 * @return
 */
    CResultSet *CDbSqlite::getTables(const char *pattern) {
        std::string sql = "select tbl_name from sqlite_master where type='table' and tbl_name like '";
        sql += pattern;
        sql += "'";

        return query(sql.c_str());
    }
}

